<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>ECMAScript_delete</title>
    <script>
        /*
        delete关键字的作用：
        删除对象的属性 语法：delete 对象.属性
        可以删除没有使用var关键字声明的全局变量（直接定义在window上面的属性）
        delete关键字的使用注意：

        返回值类型为布尔值（true / false），删除成功返回true
        删除对象中不存在的属性，返回值是true
        删除对象的原型对象中的属性（不能删除），返回值是true
        无法删除使用var声明的全局的变量，但是却可以删除直接定义在window上面的属性
        */
      
        
        // 有时候粘贴过去的代码因为格式等问题有问题会造成莫名的错误 
        function testDelete(){

                // 这种内置函数也是
                function func() {
                var num1 = 10;
                num2 = 20;
                }
        
                var dog = {
                    name:"招财",
                    age:14
                }
                //删除对象的属性
                console.log(delete dog.name);  //true
                console.log(dog.name);         //undefined

                // 删除对象中不存在的属性
                console.log(delete dog.eat);  //true
                // 删除对象的原型对象中的属性
                Object.prototype.play =  "玩";
                console.log(delete Object.prototype.play );  //true
                //没有使用var关键字声明的变量,那么该变量默认会成为一个全局的变量(变成window的属性)
                b = "testb";
                console.log(b); // testb
                func();
                //console.log(num1);  // 报错 无法在函数体外部访问局部变量
                console.log(num2);    //20   num2 变成了window的属性
                //使用delete删除直接定义在window上面的属性
                console.log(delete num2);   // true
                //console.log(num2);        // 报错
                var a = "testa";
                delete a; // 无法删除
                console.log(a);   // testa
        } 
        
        // 测试第二种删除 
        /*
        简介
        用来删除一个对象的属性。

        语法

        delete expresson
        1
        2
        express 应该是一个对象的引用,例如


        delete object.property
        delete object['property']
        1
        2
        3
        4
        如果expression不是一个对象的引用，那么delete则不会起任何作用

        返回值
        在严格模式下，如果属性是一个不可配置的属性，删除是会抛出异常，非严格模式下返回false,其他情况返回true.
        --------------------- 

        作用
        可以删除隐式全局变量，但不可已删除显示全局变量。 
        全局变量其实是global对象(window)的属性。

        x = 10;
        var y = 20;

        delete x; //true;
        delete y; //false
        内置对象的内置属性不能被删除，用户自定义的属性可以被删除。

        obj = {

            h : 10
        }

        var obj1 = {
            h: 10
        }

        delete Math.PI; // false
        delte obj.h; //true
        delete obj; //ture ,obj 是全局变量的属性，而不是变量。

        delete obj1.h;//true
        delete obj1; //false 全局显示变量不能被删除


        function fn(){
            var z = 10;
            delete z; //false
            //z是局部变量，不能被删除，delete只能删除对象的属性。
        }

        delete fn; //false
        //fn 相当于是一个匿名变量，所以也不能被删除。
      
      不能删除一个对象从原型继承而来的属性，但是可以直接从原型上删掉它；

        function foo(){}
        foo.prototype.name = 'zhangsan';

        var f = new foo();

        //delete只能删除自己的属性，不能删除继承来的属性
        delete f.name; // false 

        console.log(f.name);//zhangsan

        delete foo.prototype.anme; // true

        console.log(f.name); // undefined
        --------------------- 
       
        删除数组元素
        当删除数组元素时，数组的长度并不会变小。


        var arr = [1,3,4,6,73,2];
        delete arr[2];

        console.log(arr.length); // 6
        console.log(arr[2]); //undefiend
        consoel.log(arr); //[ 1, 3, , 6, 73, 2 ]

        作用：在forEach 循环中删除元素，不会影响循环结果


        var arr = [1,3,5,21,3,4,53,21,5,2];

        arr.forEach(function(val,index){

            if(val < 10){

                delete arr[index];
            }
        })

        console.log(arr); //[ , , , 21, , , 53, 21, ,  ]

        //可以使用filter过滤掉空值 [ 21, 53, 21 ]
        arr = arr.filter(function(val){return val});

        与 Array.splice 对比


        arr.forEach(function(val,index){

            if(val < 10){

                arr.splice(index,1);
            }
        })

        //没有答案我们预想的结果，因为splice删除元素会改变数组的长度。
        //所以说删除一个值后，其后的那个值占据了它的位置，在判断的时候就会漏掉。
        console.log(arr);// [ 3, 21, 4, 53, 21, 2 ]
        --------------------- 
        作者：輘酆 
        来源：CSDN 
        原文：https://blog.csdn.net/qq_20678155/article/details/68926620 
        版权声明：本文为博主原创文章，转载请附上博文链接！

        */
        function testDeleteTwo(){
            var arr = [1,3,5,21,3,4,53,21,5,2];

            arr.forEach(function(val,index){

                if(val < 10){

                    delete arr[index];
                }
            })

            console.log(arr); //[ , , , 21, , , 53, 21, ,  ]

            //可以使用filter过滤掉空值 [ 21, 53, 21 ]
            arr = arr.filter(function(val){return val});
            
            console.log(arr); //[21,53,21]

            
        }
        
        // 对比数组的 splice  删除一个后面的元素往前移动 index 却还是按照 0 1，2 等递增造成删除的不对 然后还有及时index 越界也不会闪退
        function compareSplice(){
            var arr = [1,3,5,21,3,4,53,21,5,2];

            arr.forEach(function(val,index){

            if(val < 10){

               arr.splice(index,1)
            }
            })
            console.log(arr); //[3,21,4,53,21,2]
        }



    </script>
</head>
<body>
    <button onclick="testDelete()" type="button">delete 关键字测试</button>
    <button onclick="testDeleteTwo()" type="button">delete 关键字测试 第二步</button>
    <button onclick="compareSplice()" type="button">和数组splice 的对比</button>
</body>
</html>